package com.approval.service;

import com.alibaba.fastjson.JSON;
import com.approval.dto.ProcessValidationResult;
import com.approval.entity.ApprovalInstance;
import com.approval.entity.ApprovalProcess;
import com.approval.entity.User;
import com.approval.exception.BusinessException;
import com.approval.mapper.ApprovalProcessMapper;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.flowable.bpmn.model.*;
import org.flowable.bpmn.model.Process;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.repository.Deployment;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class ApprovalProcessService {

    @Autowired
    private ApprovalProcessMapper processMapper;

    @Autowired
    private RepositoryService repositoryService;

    @Autowired
    private UserService userService;

    @Autowired
    @Lazy
    private ApprovalInstanceService instanceService;

    @Transactional
    public ApprovalProcess createProcess(ApprovalProcess process) {
        // 如果没有提供processKey，自动生成一个
        if (process.getProcessKey() == null || process.getProcessKey().trim().isEmpty()) {
            String processKey = "process_" + System.currentTimeMillis();
            process.setProcessKey(processKey);
        }

        // 允许processKey重复，支持版本管理

        // 设置创建人信息
        User currentUser = userService.getCurrentUser();
        if (currentUser != null) {
            process.setCreatorName(currentUser.getName());
        }

        process.setCreateTime(new Date());
        process.setUpdateTime(new Date());
        processMapper.insert(process);

        // 部署到Flowable引擎
        deployProcess(process);

        return process;
    }

    @Transactional
    public ApprovalProcess updateProcess(Long id, ApprovalProcess process) {
        ApprovalProcess existingProcess = processMapper.selectById(id);
        if (existingProcess == null) {
            throw new BusinessException("流程不存在");
        }

        // 验证流程Key是否已被其他流程使用
        String newProcessKey = process.getProcessKey();
        String existingProcessKey = existingProcess.getProcessKey();

        // 如果新流程Key不为空且与现有流程Key不同，则检查重复性
        if (newProcessKey != null && !newProcessKey.equals(existingProcessKey)) {
            ApprovalProcess duplicateProcess = processMapper.selectByProcessKey(newProcessKey);
            if (duplicateProcess != null) {
                throw new BusinessException("流程Key已被其他流程使用");
            }
        } else if (newProcessKey == null) {
            // 如果新流程Key为空，保持原有的流程Key
            process.setProcessKey(existingProcessKey);
        }

        process.setId(id);
        process.setUpdateTime(new Date());
        processMapper.update(process);

        // 重新部署到Flowable引擎
        deployProcess(process);

        return process;
    }

    @Transactional
    public void deleteProcess(Long id) {
        ApprovalProcess process = processMapper.selectById(id);
        if (process == null) {
            throw new BusinessException("流程不存在");
        }

        // 删除Flowable部署
        try {
            repositoryService.deleteDeployment(process.getProcessDefinitionId(), true);
        } catch (Exception e) {
            // 忽略删除失败的情况
        }

        processMapper.deleteById(id);
    }

    public ApprovalProcess getProcessById(Long id) {
        return processMapper.selectById(id);
    }

    public ApprovalProcess getProcessByKey(String processKey) {
        // 获取最新版本的流程
        return processMapper.selectByProcessKey(processKey);
    }

    public List<ApprovalProcess> getAllProcessesByKey(String processKey) {
        // 获取指定processKey的所有版本
        return processMapper.selectAllByProcessKey(processKey);
    }

    public List<ApprovalProcess> getAllProcesses() {
        // 只返回最新版本的流程
        return processMapper.selectLatestVersions();
    }

    public List<ApprovalProcess> getActiveProcesses() {
        return processMapper.selectByStatus(1);
    }

    private void deployProcess(ApprovalProcess process) {
        try {
            // 解析流程XML
            BpmnModel bpmnModel = parseProcessXml(process.getProcessXml());

            // 部署到Flowable引擎
            Deployment deployment = repositoryService.createDeployment()
                .name(process.getProcessName())
                .addBpmnModel(process.getProcessKey() + ".bpmn20.xml", bpmnModel)
                .deploy();

            // 更新流程定义ID
            process.setProcessDefinitionId(deployment.getId());
            processMapper.update(process);
        } catch (Exception e) {
            throw new BusinessException("流程部署失败: " + e.getMessage());
        }
    }

    private BpmnModel parseProcessXml(String processXml) {
        try {
            // 这里应该使用BPMN解析器来解析XML
            // 为了简化，我们创建一个基本的BPMN模型
            BpmnModel bpmnModel = new BpmnModel();

            Process process = new Process();
            process.setId("process");
            process.setName("Process");

            // 添加开始事件
            StartEvent startEvent = new StartEvent();
            startEvent.setId("startEvent");
            startEvent.setName("开始");
            process.addFlowElement(startEvent);

            // 添加用户任务
            UserTask userTask = new UserTask();
            userTask.setId("userTask");
            userTask.setName("审批任务");
            process.addFlowElement(userTask);

            // 添加结束事件
            EndEvent endEvent = new EndEvent();
            endEvent.setId("endEvent");
            endEvent.setName("结束");
            process.addFlowElement(endEvent);

            // 添加序列流
            SequenceFlow flow1 = new SequenceFlow();
            flow1.setId("flow1");
            flow1.setSourceRef("startEvent");
            flow1.setTargetRef("userTask");
            process.addFlowElement(flow1);

            SequenceFlow flow2 = new SequenceFlow();
            flow2.setId("flow2");
            flow2.setSourceRef("userTask");
            flow2.setTargetRef("endEvent");
            process.addFlowElement(flow2);

            bpmnModel.addProcess(process);

            return bpmnModel;
        } catch (Exception e) {
            throw new BusinessException("流程XML解析失败: " + e.getMessage());
        }
    }

    // 获取带权限的流程列表
    public List<Map<String, Object>> getAllProcessesWithPermission() {
        User currentUser = userService.getCurrentUser();
        List<ApprovalProcess> processes = getAllProcesses();

        // 根据发起人权限过滤流程
        return processes.stream()
            .filter(process -> hasProcessPermission(process, currentUser))
            .map(this::convertProcessToMap)
            .collect(Collectors.toList());
    }

    // 检查用户是否有流程权限
    private boolean hasProcessPermission(ApprovalProcess process, User currentUser) {
        try {
            // 解析流程配置
            String processConfigJson = process.getProcessConfig();
            if (processConfigJson == null || processConfigJson.trim().isEmpty()) {
                // 没有配置发起人权限，所有人都可以访问
                return true;
            }

            // 解析JSON配置
            ObjectMapper objectMapper = new ObjectMapper();
            JsonNode processConfig = objectMapper.readTree(processConfigJson);

            // 获取发起人配置 - 需要从props节点中获取
            JsonNode propsNode = processConfig.get("props");
            if (propsNode == null || propsNode.isNull()) {
                // 没有props配置，所有人都可以访问
                return true;
            }

            JsonNode assignedUserNode = propsNode.get("assignedUser");
            if (assignedUserNode == null || assignedUserNode.isNull() ||
                (assignedUserNode.isArray() && assignedUserNode.size() == 0)) {
                // 发起人为空，所有人都可以访问
                return true;
            }

            // 检查当前用户是否在发起人列表中
            if (assignedUserNode.isArray()) {
                for (JsonNode userNode : assignedUserNode) {
                    if (userNode.has("id") && userNode.get("id").asLong() == currentUser.getId()) {
                        return true;
                    }
                    if (userNode.has("userId") && userNode.get("userId").asLong() == currentUser.getId()) {
                        return true;
                    }
                }
            }

            // 用户不在发起人列表中
            return false;

        } catch (Exception e) {
            // 解析失败时，默认允许访问
            return true;
        }
    }

    // 验证流程
    public ProcessValidationResult validateProcess(String processXml) {
        ProcessValidationResult result = new ProcessValidationResult();
        try {
            parseProcessXml(processXml);
            result.setValid(true);
            result.setMessage("流程验证通过");
        } catch (Exception e) {
            result.setValid(false);
            result.setMessage("流程验证失败: " + e.getMessage());
        }
        return result;
    }

    // 导入流程
    public ApprovalProcess importProcess(Map<String, Object> processData) {
        ApprovalProcess process = new ApprovalProcess();
        process.setProcessName((String) processData.get("processName"));
        process.setProcessKey((String) processData.get("processKey"));
        process.setProcessXml((String) processData.get("processXml"));
        process.setDescription((String) processData.get("description"));
        process.setStatus(1);
        return createProcess(process);
    }

    // 导出流程
    public Map<String, Object> exportProcess(Long processId) {
        ApprovalProcess process = getProcessById(processId);
        if (process == null) {
            throw new BusinessException("流程不存在");
        }

        Map<String, Object> exportData = new HashMap<>();
        exportData.put("processName", process.getProcessName());
        exportData.put("processKey", process.getProcessKey());
        exportData.put("processXml", process.getProcessXml());
        exportData.put("description", process.getDescription());
        exportData.put("status", process.getStatus());

        return exportData;
    }

    // 获取流程模板
    public List<ApprovalProcess> getProcessTemplates() {
        return processMapper.selectByStatus(1); // 返回激活的流程作为模板
    }

    // 保存为模板
    public ApprovalProcess saveAsTemplate(Long processId, Map<String, Object> templateData) {
        ApprovalProcess originalProcess = getProcessById(processId);
        if (originalProcess == null) {
            throw new BusinessException("流程不存在");
        }

        ApprovalProcess template = new ApprovalProcess();
        template.setProcessName((String) templateData.getOrDefault("templateName", originalProcess.getProcessName() + "_模板"));
        template.setProcessKey(originalProcess.getProcessKey() + "_template");
        template.setProcessXml(originalProcess.getProcessXml());
        template.setDescription((String) templateData.getOrDefault("description", "流程模板"));
        template.setStatus(1);

        return createProcess(template);
    }

    // 批量删除流程
    public void batchDeleteProcesses(List<Long> processIds) {
        for (Long processId : processIds) {
            deleteProcess(processId);
        }
    }

    // 批量更新状态
    public void batchUpdateStatus(List<Long> processIds, Integer status) {
        for (Long processId : processIds) {
            ApprovalProcess process = getProcessById(processId);
            if (process != null) {
                process.setStatus(status);
                processMapper.update(process);
            }
        }
    }

    /**
     * 获取流程的所有历史版本
     */
    public List<ApprovalProcess> getProcessHistoryVersions(String processKey) {
        // 直接使用processKey查询所有版本
        return processMapper.selectAllVersionsByProcessKey(processKey);
    }

    /**
     * 获取流程的最新版本（根据processKey）
     */
    public ApprovalProcess getLatestProcessByKey(String processKey) {
        // 直接使用selectByProcessKey获取最新版本
        return processMapper.selectByProcessKey(processKey);
    }

    // 检查流程权限
    public Map<String, Object> checkProcessPermission(Long processId) {
        User currentUser = userService.getCurrentUser();
        // 这里可以根据用户权限检查是否有权限访问该流程
        Map<String, Object> result = new HashMap<>();
        result.put("hasPermission", true);
        result.put("message", "用户有权限访问该流程");
        return result;
    }

    // 将ApprovalProcess转换为Map
    public Map<String, Object> convertProcessToMap(ApprovalProcess process) {
        Map<String, Object> processMap = new HashMap<>();
        processMap.put("id", process.getId());
        processMap.put("processName", process.getProcessName());
        processMap.put("processKey", process.getProcessKey());
        processMap.put("category", process.getCategory());
        processMap.put("processXml", process.getProcessXml());
        processMap.put("formConfig", process.getFormConfig());
        processMap.put("processConfig", process.getProcessConfig());
        processMap.put("description", process.getDescription());
        processMap.put("status", process.getStatus());
        processMap.put("processDefinitionId", process.getProcessDefinitionId());
        processMap.put("creatorName", process.getCreatorName());
        processMap.put("createTime", process.getCreateTime());
        processMap.put("updateTime", process.getUpdateTime());
        processMap.put("icon", process.getIcon());

        // 添加版本信息
        processMap.put("version", process.getVersion());
        processMap.put("isNewVersion", process.getIsNewVersion());

        // 添加权限相关字段
        processMap.put("canStart", canStartProcess(process));
        processMap.put("permissionMessage", getPermissionMessage(process));

        return processMap;
    }

    // 检查是否可以启动流程
    private boolean canStartProcess(ApprovalProcess process) {
        // 流程必须启用
        if (process.getStatus() == null || process.getStatus() != 1) {
            return false;
        }

        // 流程必须有processKey
        if (process.getProcessKey() == null || process.getProcessKey().trim().isEmpty()) {
            return false;
        }

        // 流程必须有表单配置
        if (process.getFormConfig() == null || process.getFormConfig().trim().isEmpty()) {
            return false;
        }

        // 这里可以添加更多权限检查逻辑
        // 比如检查用户是否有权限启动该流程

        return true;
    }

    // 获取权限消息
    private String getPermissionMessage(ApprovalProcess process) {
        if (process.getStatus() == null || process.getStatus() != 1) {
            return "流程已禁用";
        }

        if (process.getProcessKey() == null || process.getProcessKey().trim().isEmpty()) {
            return "流程未配置流程Key";
        }

        if (process.getFormConfig() == null || process.getFormConfig().trim().isEmpty()) {
            return "流程未配置表单";
        }

        return "";
    }

    /**
     * 检查流程是否有正在运行的实例
     */
    public boolean hasRunningInstances(Long processId) {
        try {
            // 查询该流程是否有状态为RUNNING的实例
            List<ApprovalInstance> runningInstances = instanceService.getInstancesByProcessIdAndStatus(processId, "RUNNING");
            return runningInstances != null && !runningInstances.isEmpty();
        } catch (Exception e) {
            // 查询失败时，为了安全起见，假设有正在运行的实例
            return true;
        }
    }

    /**
     * 获取流程的正在运行实例数量
     */
    public int getRunningInstanceCount(Long processId) {
        try {
            List<ApprovalInstance> runningInstances = instanceService.getInstancesByProcessIdAndStatus(processId, "RUNNING");
            return runningInstances != null ? runningInstances.size() : 0;
        } catch (Exception e) {
            return 0;
        }
    }

    /**
     * 更新流程（带版本管理）
     */
    @Transactional
    public ApprovalProcess updateProcessWithVersionManagement(Long processId, ApprovalProcess updatedProcess, String updateStrategy) {
        ApprovalProcess existingProcess = getProcessById(processId);
        if (existingProcess == null) {
            throw new BusinessException("流程不存在");
        }

        // 检查是否有正在运行的实例
        boolean hasRunningInstances = hasRunningInstances(processId);

        if (hasRunningInstances) {
            // 有正在运行的实例，根据策略处理
            switch (updateStrategy) {
                case "CREATE_NEW_VERSION":
                    // 创建新版本，老实例继续使用老版本
                    return createNewVersion(existingProcess, updatedProcess);
                case "FORCE_UPDATE":
                    // 强制更新，可能影响正在运行的实例
                    return forceUpdateProcess(existingProcess, updatedProcess);
                case "REJECT_UPDATE":
                    // 拒绝更新
                    throw new BusinessException("流程有正在运行的实例，无法更新。请等待实例完成或选择其他更新策略。");
                default:
                    throw new BusinessException("无效的更新策略");
            }
        } else {
            // 没有正在运行的实例，创建新版本（推荐策略）
            return createNewVersion(existingProcess, updatedProcess);
        }
    }

    /**
     * 创建新版本流程（对用户透明）
     */
    private ApprovalProcess createNewVersion(ApprovalProcess oldProcess, ApprovalProcess newProcess) {
        // 将老流程标记为非新版本
        oldProcess.setIsNewVersion(false);
        processMapper.update(oldProcess);

        // 创建新版本流程（保持相同的processKey，用户感知不到）
        ApprovalProcess newVersionProcess = new ApprovalProcess();
        newVersionProcess.setProcessName(newProcess.getProcessName());

        // 保持相同的processKey，这样用户感知不到版本变化
        String baseProcessKey = oldProcess.getProcessKey();
        if (baseProcessKey == null || baseProcessKey.trim().isEmpty()) {
            baseProcessKey = "process_" + System.currentTimeMillis();
        }
        newVersionProcess.setProcessKey(baseProcessKey); // 不添加版本后缀

        newVersionProcess.setCategory(newProcess.getCategory());
        newVersionProcess.setProcessXml(newProcess.getProcessXml());
        newVersionProcess.setFormConfig(newProcess.getFormConfig());
        newVersionProcess.setProcessConfig(newProcess.getProcessConfig());
        newVersionProcess.setDescription(newProcess.getDescription());
        newVersionProcess.setIcon(newProcess.getIcon());
        newVersionProcess.setStatus(1);
        newVersionProcess.setVersion(oldProcess.getVersion() + 1);
        newVersionProcess.setIsNewVersion(true);
        newVersionProcess.setCreatorName(oldProcess.getCreatorName());
        newVersionProcess.setCreateTime(new Date());
        newVersionProcess.setUpdateTime(new Date());

        return createProcess(newVersionProcess);
    }

    /**
     * 强制更新流程（可能影响正在运行的实例）
     */
    private ApprovalProcess forceUpdateProcess(ApprovalProcess existingProcess, ApprovalProcess updatedProcess) {
        // 更新版本号
        existingProcess.setVersion(existingProcess.getVersion() + 1);
        existingProcess.setIsNewVersion(true);

        // 更新流程内容
        existingProcess.setProcessName(updatedProcess.getProcessName());
        existingProcess.setCategory(updatedProcess.getCategory());
        existingProcess.setProcessXml(updatedProcess.getProcessXml());
        existingProcess.setFormConfig(updatedProcess.getFormConfig());
        existingProcess.setProcessConfig(updatedProcess.getProcessConfig());
        existingProcess.setDescription(updatedProcess.getDescription());
        existingProcess.setIcon(updatedProcess.getIcon());
        existingProcess.setUpdateTime(new Date());

        processMapper.update(existingProcess);
        return existingProcess;
    }
}
